home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 40
/
Aminet 40 (2000)(Schatztruhe)[!][Dec 2000].iso
/
Aminet
/
comm
/
tcp
/
rxsocket.lha
/
rxsocket
/
Examples
/
ping.rexx
< prev
next >
Wrap
OS/2 REXX Batch file
|
1999-05-29
|
4KB
|
169 lines
/*
This code is NOT from Berkley, but FROM ME :-)
Very stupid Arexx ping.
Don't use it to ping localhost or you would ROTFL.
Usage: ping <HOST> [SIZE/N] [NUM/N] [QUICK/S]
HOST the host name to ping
SIZE the size of the imcp echo packet
NUM the number of packet to send - 0 means continuos
QUICK don't delay, send fast
*/
l="rmh.library";if ~show("L",l) then;if ~addlib(l,0,-30) then exit
if AddLibrary("rexxsupport.library","rxsocket.library")~=0 then exit
prg = ProgramName("NOEXT")
/** read and parse arguments **/
if ~RMH_ReadArgs("HOST/A,SIZE/K/N,NUM/K/N,QUICK/S") then do
call PrintFault(IoErr(),prg)
exit
end
addr = resolve(parm.0.value)
if addr=="-1" then call err "no host <"parm.0.value">"
host=parm.0.value
if parm.1.flag then
if parm.1.value>7 & parm.1.value<8000 then dataSize=parm.1.value
else call err("SIZE must be >7 and <8000")
else dataSize=56
if parm.2.flag then
if parm.2.value>0 then numPkt=parm.2.value
else call err("NUM must be positive")
else numPkt=1E10
wait=~parm.3.flag
break=0
signal on BREAK_C
/** resolve host name **/
sin.addrAddr=resolve(host)
if sin.addrAddr=="-1" then call err("HOST not found")
/** create a RAW ICMP socket **/
sock=socket("INET","RAW","ICMP")
if sock<0 then call err("no socket")
/** socket must NOT blocking **/
call IOCtlSocket(sock,"FIONBIO",1)
/** we need an ID to recognize our icmp **/
ourID=right(x2c(pragma("ID")),2)
min=1E10
max=0
avg=0
nrec=0
ntrans=0
/** create a timer **/
t=CreateTimer()
timSig=TimerSignal(t)
if numPkt==1E10 then ps=""
else ps=" Num:" numPkt
say Upper(PRG) host "("sin.addrAddr"):" dataSize "data bytes" ps
/** we go:
wait_for_packet_or_time_to_send
readpacket if any
sendpacket if time
**/
call StartTimer(t,wait)
call sendPacket(dataSize)
sel.read.0=sock
go=ntrans<numPkt | numPkt==1
do while go
res=WaitSelect("SEL",,,timSig)
if res~=0 then call readPacket
if and(sel.signals,timSig)~=0 then do
call sendPacket(dataSize)
if wait==0 then call WriteCH("STDOUT",".")
call StartTimer(t,wait)
end
go=ntrans<numPkt
end
signal BREAK_C
exit
err:
parse arg msg
say prg":" msg
exit
pad: PROCEDURE
parse arg string,len
return copies(d2c(0),len-length(string)) || string
d2m: PROCEDURE
parse arg val,len
return pad(d2c(val),len)
sendPacket:
parse arg dataSize
/** here we create an ICMP echo packet **/
pktf = ourID || d2m(ntrans,2)
call GetSysTime("TV")
pktf=pktf || d2m(tv.secs,4) || d2m(tv.micro,4) || copies("0"x,dataSize-8)
temp="0800"x || "0000"x || pktf
pkt="0800"x || d2c(InetCksum(temp)) || pktf
res=SendTo(sock,pkt,0,"SIN")
if res~=length(pkt) then do
e=errno()
if IsLibOn("TTCP") then es=e
else es=ErrorString(e)
call err("send error ("es")")
end
ntrans=ntrans+1
return
readPacket:
/** here we read an ICMP packet and check if it is an ICMP
echo-replay for us **/
call GetSysTime("NOW")
res=RecvFrom(sock,"BUFF",256)
if res<0 then call err("recv error")
parse var buff vhl +1 tos +1 len +2 id +2 off +2 ttl +1 rest
hl=c2d(bitand(vhl,'F'x))*8
buff=c2x(buff)
parse var buff +hl type +2 code +2 cksum +4 id +4 seq +4 s +8 m +8 data
if c2d(len)~=dataSize+8 | type~='00' | code~='00' | id~=c2x(ourID)
then return
old.secs=x2d(s)
old.micro=x2d(m)
call SubTime("NOW","OLD")
time=now.secs*1000000+now.micro
time=time%1000"."time//1000
time=((time*100)%1)/100
if wait==1 then
say c2d(len) "bytes from" sin.AddrAddr": icmp_seq="x2d(seq) "ttl="c2d(ttl) "time="time "ms"
nrec=nrec+1
if time>max then max=time
if time<min then min=time
avg=avg+time
return
/** statistics **/
BREAK_C:
if break==1 | sigl<38 then call err("user break")
if t~="T" then call StopTimer(t)
break=1
signal on BREAK_C
if ntrans>nrec & max>0 then do
res=WaitSelect("SEL",5)
if res~=0 then call readPacket
end
if ntrans==0 then loss=100
else loss=(ntrans-nrec)/ntrans*100
say
say "---" host "ping statistics ---"
say ntrans "packets transmitted," nrec "packets received," loss"% packet loss"
if nrec>0 then say "round-trip min/avg/max =" min"/"|| (((avg/nrec)*100)%1)/100 || "/"max "ms"
exit